<!DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>A Crash Course | Vue Test Utils</title>
    <meta name="description" content="The documentation for the official Vue Test Utils">
    <link rel="stylesheet" href="static/css/style.fa57c02b.css">
    <link rel="modulepreload" href="https://test-utils.vuejs.org/assets/chunks/AlgoliaSearchBox.e05398bd.js">
    <link rel="modulepreload" href="https://test-utils.vuejs.org/assets/app.49122d47.js">
    <link rel="modulepreload" href="https://test-utils.vuejs.org/assets/guide_essentials_a-crash-course.md.2a557e7a.lean.js">
    
    <link rel="icon" href="https://test-utils.vuejs.org/logo.png">
  <meta name="twitter:title" content="A Crash Course | Vue Test Utils">
  <meta property="og:title" content="A Crash Course | Vue Test Utils">
  </head>
  <body>
    <div id="app"><!--[--><div class="theme"><header class="nav-bar" data-v-675d8756=""><div class="sidebar-button" data-v-675d8756=""><svg class="icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewbox="0 0 448 512"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z" class=""></path></svg></div><a class="nav-bar-title" href="javascript:;" aria-label="Vue Test Utils, back to home" data-v-675d8756="" data-v-cc01ef16=""><!----> Vue Test Utils</a><div class="flex-grow" data-v-675d8756=""></div><div class="nav" data-v-675d8756=""><nav class="nav-links" data-v-675d8756="" data-v-eab3edfe=""><!--[--><div class="item" data-v-eab3edfe=""><div class="nav-link" data-v-eab3edfe="" data-v-b8818f8c=""><a class="item active" href="javascript:;" data-v-b8818f8c="">Guide <!----></a></div></div><div class="item" data-v-eab3edfe=""><div class="nav-link" data-v-eab3edfe="" data-v-b8818f8c=""><a class="item" href="javascript:;" data-v-b8818f8c="">API Reference <!----></a></div></div><div class="item" data-v-eab3edfe=""><div class="nav-link" data-v-eab3edfe="" data-v-b8818f8c=""><a class="item" href="javascript:;" data-v-b8818f8c="">Migrating from Vue 2 <!----></a></div></div><div class="item" data-v-eab3edfe=""><div class="nav-link" data-v-eab3edfe="" data-v-b8818f8c=""><a class="item isExternal" href="javascript:;" target="_blank" rel="noopener noreferrer" data-v-b8818f8c="">Changelog <svg class="icon outbound" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewbox="0 0 100 100" width="15" height="15" data-v-b8818f8c=""><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></div></div><!--]--><!----><div class="item" data-v-eab3edfe=""><div class="nav-link" data-v-eab3edfe="" data-v-b8818f8c=""><a class="item isExternal" href="javascript:;" target="_blank" rel="noopener noreferrer" data-v-b8818f8c="">GitHub <svg class="icon outbound" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewbox="0 0 100 100" width="15" height="15" data-v-b8818f8c=""><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></div></div></nav></div><!--[--><!--[--><div class="algolia-search-box" id="docsearch"></div><!--]--><!--]--></header><aside class="sidebar" data-v-83e92a68=""><nav class="nav-links nav" data-v-83e92a68="" data-v-eab3edfe=""><!--[--><div class="item" data-v-eab3edfe=""><div class="nav-link" data-v-eab3edfe="" data-v-b8818f8c=""><a class="item active" href="javascript:;" data-v-b8818f8c="">Guide <!----></a></div></div><div class="item" data-v-eab3edfe=""><div class="nav-link" data-v-eab3edfe="" data-v-b8818f8c=""><a class="item" href="javascript:;" data-v-b8818f8c="">API Reference <!----></a></div></div><div class="item" data-v-eab3edfe=""><div class="nav-link" data-v-eab3edfe="" data-v-b8818f8c=""><a class="item" href="javascript:;" data-v-b8818f8c="">Migrating from Vue 2 <!----></a></div></div><div class="item" data-v-eab3edfe=""><div class="nav-link" data-v-eab3edfe="" data-v-b8818f8c=""><a class="item isExternal" href="javascript:;" target="_blank" rel="noopener noreferrer" data-v-b8818f8c="">Changelog <svg class="icon outbound" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewbox="0 0 100 100" width="15" height="15" data-v-b8818f8c=""><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></div></div><!--]--><!----><div class="item" data-v-eab3edfe=""><div class="nav-link" data-v-eab3edfe="" data-v-b8818f8c=""><a class="item isExternal" href="javascript:;" target="_blank" rel="noopener noreferrer" data-v-b8818f8c="">GitHub <svg class="icon outbound" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewbox="0 0 100 100" width="15" height="15" data-v-b8818f8c=""><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></div></div></nav><!--[--><!--]--><ul class="sidebar-links" data-v-83e92a68=""><!--[--><li class="sidebar-link"><a class="sidebar-link-item" href="javascript:;">Installation</a><!----></li><li class="sidebar-link"><p class="sidebar-link-item">Essentials</p><ul class="sidebar-links"><li class="sidebar-link"><a class="sidebar-link-item" href="javascript:;">Getting Started</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item active" href="javascript:;">A Crash Course</a><ul class="sidebar-links"><li class="sidebar-link"><a class="sidebar-link-item" href="#getting-started">Getting Started</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#the-first-test-a-todo-is-rendered">The first test - a todo is rendered</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#making-the-test-pass">Making the test pass</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#adding-a-new-todo">Adding a new todo</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#completing-a-todo">Completing a todo</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#arrange-act-assert">Arrange, Act, Assert</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#conclusion">Conclusion</a><!----></li></ul></li><li class="sidebar-link"><a class="sidebar-link-item" href="javascript:;">Conditional Rendering</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="javascript:;">Testing Emitted Events</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="javascript:;">Testing Forms</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="javascript:;">Passing Data to Components</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="javascript:;">Write components that are easy to test</a><!----></li></ul></li><li class="sidebar-link"><p class="sidebar-link-item">Vue Test Utils in depth</p><ul class="sidebar-links"><li class="sidebar-link"><a class="sidebar-link-item" href="javascript:;">Slots</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="javascript:;">Asynchronous Behavior</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="javascript:;">Making HTTP Requests</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="javascript:;">Transitions</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="javascript:;">Component Instance</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="javascript:;">Reusability and Composition</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="javascript:;">Testing Vuex</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="javascript:;">Testing Vue Router</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="javascript:;">Testing Teleport</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="javascript:;">Stubs and Shallow Mount</a><!----></li></ul></li><li class="sidebar-link"><p class="sidebar-link-item">Extending Vue Test Utils</p><ul class="sidebar-links"><li class="sidebar-link"><a class="sidebar-link-item" href="javascript:;">Plugins</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="javascript:;">Community and Learning</a><!----></li></ul></li><li class="sidebar-link"><a class="sidebar-link-item" href="javascript:;">Migrating from Vue 2</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="javascript:;">API Reference</a><!----></li><!--]--></ul><!--[--><!--]--></aside><div class="sidebar-mask"></div><main class="page" data-v-7eddb2c4=""><div class="container" data-v-7eddb2c4=""><!--[--><!--]--><div style="position:relative;" class="content" data-v-7eddb2c4=""><div><h1 id="a-crash-course" tabindex="-1">A Crash Course <a class="header-anchor" href="#a-crash-course" aria-hidden="true">#</a></h1><p>Let&#39;s jump right into it! Let&#39;s learn Vue Test Utils (VTU) by building a simple Todo app and writing tests as we go. This guide will cover how to:</p><ul><li>Mount components</li><li>Find elements</li><li>Fill out forms</li><li>Trigger events</li></ul><h2 id="getting-started" tabindex="-1">Getting Started <a class="header-anchor" href="#getting-started" aria-hidden="true">#</a></h2><p>We will start off with a simple <code>TodoApp</code> component with a single todo:</p><div class="language-vue"><pre><code><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>template</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>template</span><span class="token punctuation">&gt;</span></span>

<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">&gt;</span></span><span class="token script"><span class="token language-javascript">
<span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token punctuation">{</span>
  <span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">&#39;TodoApp&#39;</span><span class="token punctuation">,</span>

  <span class="token function">data</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token punctuation">{</span>
      <span class="token literal-property property">todos</span><span class="token operator">:</span> <span class="token punctuation">[</span>
        <span class="token punctuation">{</span>
          <span class="token literal-property property">id</span><span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">,</span>
          <span class="token literal-property property">text</span><span class="token operator">:</span> <span class="token string">&#39;Learn Vue.js 3&#39;</span><span class="token punctuation">,</span>
          <span class="token literal-property property">completed</span><span class="token operator">:</span> <span class="token boolean">false</span>
        <span class="token punctuation">}</span>
      <span class="token punctuation">]</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span>
</code></pre></div><h2 id="the-first-test-a-todo-is-rendered" tabindex="-1">The first test - a todo is rendered <a class="header-anchor" href="#the-first-test-a-todo-is-rendered" aria-hidden="true">#</a></h2><p>The first test we will write verifies a todo is rendered. Let&#39;s see the test first, then discuss each part:</p><div class="language-js"><pre><code><span class="token keyword">import</span> <span class="token punctuation">{</span> mount <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">&#39;@vue/test-utils&#39;</span>
<span class="token keyword">import</span> TodoApp <span class="token keyword">from</span> <span class="token string">&#39;./TodoApp.vue&#39;</span>

<span class="token function">test</span><span class="token punctuation">(</span><span class="token string">&#39;renders a todo&#39;</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> wrapper <span class="token operator">=</span> <span class="token function">mount</span><span class="token punctuation">(</span>TodoApp<span class="token punctuation">)</span>

  <span class="token keyword">const</span> todo <span class="token operator">=</span> wrapper<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">&#39;[data-test=&quot;todo&quot;]&#39;</span><span class="token punctuation">)</span>

  <span class="token function">expect</span><span class="token punctuation">(</span>todo<span class="token punctuation">.</span><span class="token function">text</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toBe</span><span class="token punctuation">(</span><span class="token string">&#39;Learn Vue.js 3&#39;</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
</code></pre></div><p>We start off by importing <code>mount</code> - this is the main way to render a component in VTU. You declare a test by using the <code>test</code> function with a short description of the test. The <code>test</code> and <code>expect</code> functions are globally available in most test runners (this example uses <a href="javascript:;" target="_blank" rel="noopener noreferrer">Jest</a>). If <code>test</code> and <code>expect</code> look confusing, the Jest documentation has a <a href="javascript:;" target="_blank" rel="noopener noreferrer">more simple example</a> of how to use them and how they work.</p><p>Next, we call <code>mount</code> and pass the component as the first argument - this is something almost every test you write will do. By convention, we assign the result to a variable called <code>wrapper</code>, since <code>mount</code> provides a simple &quot;wrapper&quot; around the app with some convenient methods for testing.</p><p>Finally, we use another global function common to many tests runner - Jest included - <code>expect</code>. The idea is we are asserting, or <em>expecting</em>, the actual output to match what we think it should be. In this case, we are finding an element with the selector <code>data-test=&quot;todo&quot;</code> - in the DOM, this will look like <code>&lt;div data-test=&quot;todo&quot;&gt;...&lt;/div&gt;</code>. We then call the <code>text</code> method to get the content, which we expect to be <code>&#39;Learn Vue.js 3&#39;</code>.</p><blockquote><p>Using <code>data-test</code> selectors is not required, but it can make your tests less brittle. classes and ids tend to change or move around as an application grows - by using <code>data-test</code>, it&#39;s clear to other developers which elements are used in tests, and should not be changed.</p></blockquote><h2 id="making-the-test-pass" tabindex="-1">Making the test pass <a class="header-anchor" href="#making-the-test-pass" aria-hidden="true">#</a></h2><p>If we run this test now, it fails with the following error message: <code>Unable to get [data-test=&quot;todo&quot;]</code>. That&#39;s because we aren&#39;t rendering any todo item, so the <code>get()</code> call is failing to return a wrapper (remember, VTU wraps all components, and DOM elements, in a &quot;wrapper&quot; with some convenient methods). Let&#39;s update <code>&lt;template&gt;</code> in <code>TodoApp.vue</code> to render the <code>todos</code> array:</p><div class="language-vue"><pre><code><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>template</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">v-for</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>todo in todos<span class="token punctuation">&quot;</span></span> <span class="token attr-name">:key</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>todo.id<span class="token punctuation">&quot;</span></span> <span class="token attr-name">data-test</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>todo<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>
      {{ todo.text }}
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>template</span><span class="token punctuation">&gt;</span></span>
</code></pre></div><p>With this change, the test is passing. Congratulations! You wrote your first component test.</p><h2 id="adding-a-new-todo" tabindex="-1">Adding a new todo <a class="header-anchor" href="#adding-a-new-todo" aria-hidden="true">#</a></h2><p>The next feature we will be adding is for the user to be able to create a new todo. To do so, we need a form with an input for the user to type some text. When the user submits the form, we expect the new todo to be rendered. Let&#39;s take a look at the test:</p><div class="language-js"><pre><code><span class="token keyword">import</span> <span class="token punctuation">{</span> mount <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">&#39;@vue/test-utils&#39;</span>
<span class="token keyword">import</span> TodoApp <span class="token keyword">from</span> <span class="token string">&#39;./TodoApp.vue&#39;</span>

<span class="token function">test</span><span class="token punctuation">(</span><span class="token string">&#39;creates a todo&#39;</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> wrapper <span class="token operator">=</span> <span class="token function">mount</span><span class="token punctuation">(</span>TodoApp<span class="token punctuation">)</span>
  <span class="token function">expect</span><span class="token punctuation">(</span>wrapper<span class="token punctuation">.</span><span class="token function">findAll</span><span class="token punctuation">(</span><span class="token string">&#39;[data-test=&quot;todo&quot;]&#39;</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toHaveLength</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span>

  wrapper<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">&#39;[data-test=&quot;new-todo&quot;]&#39;</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">setValue</span><span class="token punctuation">(</span><span class="token string">&#39;New todo&#39;</span><span class="token punctuation">)</span>
  wrapper<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">&#39;[data-test=&quot;form&quot;]&#39;</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">trigger</span><span class="token punctuation">(</span><span class="token string">&#39;submit&#39;</span><span class="token punctuation">)</span>

  <span class="token function">expect</span><span class="token punctuation">(</span>wrapper<span class="token punctuation">.</span><span class="token function">findAll</span><span class="token punctuation">(</span><span class="token string">&#39;[data-test=&quot;todo&quot;]&#39;</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toHaveLength</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
</code></pre></div><p>As usual, we start of by using <code>mount</code> to render the element. We are also asserting that only 1 todo is rendered - this makes it clear that we are adding an additional todo, as the final line of the test suggests.</p><p>To update the <code>&lt;input&gt;</code>, we use <code>setValue</code> - this allows us to set the input&#39;s value.</p><p>After updating the <code>&lt;input&gt;</code>, we use the <code>trigger</code> method to simulate the user submitting the form. Finally, we assert the number of todo items has increased from 1 to 2.</p><p>If we run this test, it will obviously fail. Let&#39;s update <code>TodoApp.vue</code> to have the <code>&lt;form&gt;</code> and <code>&lt;input&gt;</code> elements and make the test pass:</p><div class="language-vue"><pre><code><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>template</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">v-for</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>todo in todos<span class="token punctuation">&quot;</span></span> <span class="token attr-name">:key</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>todo.id<span class="token punctuation">&quot;</span></span> <span class="token attr-name">data-test</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>todo<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>
      {{ todo.text }}
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span>

    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>form</span> <span class="token attr-name">data-test</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>form<span class="token punctuation">&quot;</span></span> <span class="token attr-name">@submit.prevent</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>createTodo<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>
      <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>input</span> <span class="token attr-name">data-test</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>new-todo<span class="token punctuation">&quot;</span></span> <span class="token attr-name">v-model</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>newTodo<span class="token punctuation">&quot;</span></span> <span class="token punctuation">/&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>form</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>template</span><span class="token punctuation">&gt;</span></span>

<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">&gt;</span></span><span class="token script"><span class="token language-javascript">
<span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token punctuation">{</span>
  <span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">&#39;TodoApp&#39;</span><span class="token punctuation">,</span>

  <span class="token function">data</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token punctuation">{</span>
      <span class="token literal-property property">newTodo</span><span class="token operator">:</span> <span class="token string">&#39;&#39;</span><span class="token punctuation">,</span>
      <span class="token literal-property property">todos</span><span class="token operator">:</span> <span class="token punctuation">[</span>
        <span class="token punctuation">{</span>
          <span class="token literal-property property">id</span><span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">,</span>
          <span class="token literal-property property">text</span><span class="token operator">:</span> <span class="token string">&#39;Learn Vue.js 3&#39;</span><span class="token punctuation">,</span>
          <span class="token literal-property property">completed</span><span class="token operator">:</span> <span class="token boolean">false</span>
        <span class="token punctuation">}</span>
      <span class="token punctuation">]</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>

  <span class="token literal-property property">methods</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token function">createTodo</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token keyword">this</span><span class="token punctuation">.</span>todos<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
        <span class="token literal-property property">id</span><span class="token operator">:</span> <span class="token number">2</span><span class="token punctuation">,</span>
        <span class="token literal-property property">text</span><span class="token operator">:</span> <span class="token keyword">this</span><span class="token punctuation">.</span>newTodo<span class="token punctuation">,</span>
        <span class="token literal-property property">completed</span><span class="token operator">:</span> <span class="token boolean">false</span>
      <span class="token punctuation">}</span><span class="token punctuation">)</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span>
</code></pre></div><p>We are using <code>v-model</code> to bind to the <code>&lt;input&gt;</code> and <code>@submit</code> to listen for the form submission. When the form is submitted, <code>createTodo</code> is called and inserts a new todo into the <code>todos</code> array.</p><p>While this looks good, running the test shows an error:</p><div class="language-"><pre><code>expect(received).toHaveLength(expected)

    Expected length: 2
    Received length: 1
    Received array:  [{&quot;element&quot;: &lt;div data-test=&quot;todo&quot;&gt;Learn Vue.js 3&lt;/div&gt;}]
</code></pre></div><p>The number of todos has not increased. The problem is that Jest executes tests in a synchronous manner, ending the test as soon as the final function is called. Vue, however, updates the DOM asynchronously. We need to mark the test <code>async</code>, and call <code>await</code> on any methods that might cause the DOM to change. <code>trigger</code> is one such methods, and so is <code>setValue</code> - we can simply prepend <code>await</code> and the test should work as expected:</p><div class="language-js"><pre><code><span class="token keyword">import</span> <span class="token punctuation">{</span> mount <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">&#39;@vue/test-utils&#39;</span>
<span class="token keyword">import</span> TodoApp <span class="token keyword">from</span> <span class="token string">&#39;./TodoApp.vue&#39;</span>

<span class="token function">test</span><span class="token punctuation">(</span><span class="token string">&#39;creates a todo&#39;</span><span class="token punctuation">,</span> <span class="token keyword">async</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> wrapper <span class="token operator">=</span> <span class="token function">mount</span><span class="token punctuation">(</span>TodoApp<span class="token punctuation">)</span>

  <span class="token keyword">await</span> wrapper<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">&#39;[data-test=&quot;new-todo&quot;]&#39;</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">setValue</span><span class="token punctuation">(</span><span class="token string">&#39;New todo&#39;</span><span class="token punctuation">)</span>
  <span class="token keyword">await</span> wrapper<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">&#39;[data-test=&quot;form&quot;]&#39;</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">trigger</span><span class="token punctuation">(</span><span class="token string">&#39;submit&#39;</span><span class="token punctuation">)</span>

  <span class="token function">expect</span><span class="token punctuation">(</span>wrapper<span class="token punctuation">.</span><span class="token function">findAll</span><span class="token punctuation">(</span><span class="token string">&#39;[data-test=&quot;todo&quot;]&#39;</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toHaveLength</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
</code></pre></div><p>Now the test is finally passing!</p><h2 id="completing-a-todo" tabindex="-1">Completing a todo <a class="header-anchor" href="#completing-a-todo" aria-hidden="true">#</a></h2><p>Now that we can create todos, let&#39;s give the user the ability to mark a todo item as completed/uncompleted with a checkbox. As previously, let&#39;s start with the failing test:</p><div class="language-js"><pre><code><span class="token keyword">import</span> <span class="token punctuation">{</span> mount <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">&#39;@vue/test-utils&#39;</span>
<span class="token keyword">import</span> TodoApp <span class="token keyword">from</span> <span class="token string">&#39;./TodoApp.vue&#39;</span>

<span class="token function">test</span><span class="token punctuation">(</span><span class="token string">&#39;completes a todo&#39;</span><span class="token punctuation">,</span> <span class="token keyword">async</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> wrapper <span class="token operator">=</span> <span class="token function">mount</span><span class="token punctuation">(</span>TodoApp<span class="token punctuation">)</span>

  <span class="token keyword">await</span> wrapper<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">&#39;[data-test=&quot;todo-checkbox&quot;]&#39;</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">setValue</span><span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">)</span>

  <span class="token function">expect</span><span class="token punctuation">(</span>wrapper<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">&#39;[data-test=&quot;todo&quot;]&#39;</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">classes</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toContain</span><span class="token punctuation">(</span><span class="token string">&#39;completed&#39;</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
</code></pre></div><p>This test is similar to the previous two; we find an element and interact with it in same way (we use <code>setValue</code> again, since we are interacting with a <code>&lt;input&gt;</code>).</p><p>Lastly, we make an assertion. We will be applying a <code>completed</code> class to completed todos - we can then use this to add some styling to visually indicate the status of a todo.</p><p>We can get this test to pass by updating the <code>&lt;template&gt;</code> to include the <code>&lt;input type=&quot;checkbox&quot;&gt;</code> and a class binding on the todo element:</p><div class="language-vue"><pre><code><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>template</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span>
      <span class="token attr-name">v-for</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>todo in todos<span class="token punctuation">&quot;</span></span>
      <span class="token attr-name">:key</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>todo.id<span class="token punctuation">&quot;</span></span>
      <span class="token attr-name">data-test</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>todo<span class="token punctuation">&quot;</span></span>
      <span class="token attr-name">:class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>[todo.completed ? <span class="token punctuation">&#39;</span>completed<span class="token punctuation">&#39;</span> : <span class="token punctuation">&#39;</span><span class="token punctuation">&#39;</span>]<span class="token punctuation">&quot;</span></span>
    <span class="token punctuation">&gt;</span></span>
      {{ todo.text }}
      <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>input</span>
        <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>checkbox<span class="token punctuation">&quot;</span></span>
        <span class="token attr-name">v-model</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>todo.completed<span class="token punctuation">&quot;</span></span>
        <span class="token attr-name">data-test</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>todo-checkbox<span class="token punctuation">&quot;</span></span>
      <span class="token punctuation">/&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span>

    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>form</span> <span class="token attr-name">data-test</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>form<span class="token punctuation">&quot;</span></span> <span class="token attr-name">@submit.prevent</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>createTodo<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>
      <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>input</span> <span class="token attr-name">data-test</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>new-todo<span class="token punctuation">&quot;</span></span> <span class="token attr-name">v-model</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>newTodo<span class="token punctuation">&quot;</span></span> <span class="token punctuation">/&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>form</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>template</span><span class="token punctuation">&gt;</span></span>
</code></pre></div><p>Congratulations! You wrote your first component tests.</p><h2 id="arrange-act-assert" tabindex="-1">Arrange, Act, Assert <a class="header-anchor" href="#arrange-act-assert" aria-hidden="true">#</a></h2><p>You may have noticed some new lines between the code in each of the tests. Let&#39;s look at the second test again, in detail:</p><div class="language-js"><pre><code><span class="token keyword">import</span> <span class="token punctuation">{</span> mount <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">&#39;@vue/test-utils&#39;</span>
<span class="token keyword">import</span> TodoApp <span class="token keyword">from</span> <span class="token string">&#39;./TodoApp.vue&#39;</span>

<span class="token function">test</span><span class="token punctuation">(</span><span class="token string">&#39;creates a todo&#39;</span><span class="token punctuation">,</span> <span class="token keyword">async</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> wrapper <span class="token operator">=</span> <span class="token function">mount</span><span class="token punctuation">(</span>TodoApp<span class="token punctuation">)</span>

  <span class="token keyword">await</span> wrapper<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">&#39;[data-test=&quot;new-todo&quot;]&#39;</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">setValue</span><span class="token punctuation">(</span><span class="token string">&#39;New todo&#39;</span><span class="token punctuation">)</span>
  <span class="token keyword">await</span> wrapper<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">&#39;[data-test=&quot;form&quot;]&#39;</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">trigger</span><span class="token punctuation">(</span><span class="token string">&#39;submit&#39;</span><span class="token punctuation">)</span>

  <span class="token function">expect</span><span class="token punctuation">(</span>wrapper<span class="token punctuation">.</span><span class="token function">findAll</span><span class="token punctuation">(</span><span class="token string">&#39;[data-test=&quot;todo&quot;]&#39;</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toHaveLength</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
</code></pre></div><p>The test is split into three distinct stages, separated by new lines. The three stages represent the three phases of a test: <strong>arrange</strong>, <strong>act</strong> and <strong>assert</strong>.</p><p>In the <em>arrange</em> phase, we are setting up the scenario for the test. A more complex example may require creating a Vuex store, or populating a database.</p><p>In the <em>act</em> phase, we act out the scenario, simulating how a user would interact with the component or application.</p><p>In the <em>assert</em> phase, we make assertions about how we expect the current state of the component to be.</p><p>Almost all test will follow these three phases. You don&#39;t need to separate them with new lines like this guide does, but it is good to keep these three phases in mind as you write your tests.</p><h2 id="conclusion" tabindex="-1">Conclusion <a class="header-anchor" href="#conclusion" aria-hidden="true">#</a></h2><ul><li>Use <code>mount()</code> to render a component.</li><li>Use <code>get()</code> and <code>findAll()</code> to query the DOM.</li><li><code>trigger()</code> and <code>setValue()</code> are helpers to simulate user input.</li><li>Updating the DOM is an async operation, so make sure to use <code>async</code> and <code>await</code>.</li><li>Testing usually consists of 3 phases; arrange, act and assert.</li></ul></div></div><footer class="page-footer" data-v-7eddb2c4="" data-v-07c132fc=""><div class="edit" data-v-07c132fc=""><div class="edit-link" data-v-07c132fc="" data-v-1ed99556=""><a class="link" href="javascript:;" target="_blank" rel="noopener noreferrer" data-v-1ed99556="">Edit this page <svg class="icon outbound icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewbox="0 0 100 100" width="15" height="15" data-v-1ed99556=""><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></div></div><div class="updated" data-v-07c132fc=""><!----></div></footer><div class="next-and-prev-link" data-v-7eddb2c4="" data-v-38ede35f=""><div class="container" data-v-38ede35f=""><div class="prev" data-v-38ede35f=""><a class="link" href="javascript:;" data-v-38ede35f=""><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24" class="icon icon-prev" data-v-38ede35f=""><path d="M19,11H7.4l5.3-5.3c0.4-0.4,0.4-1,0-1.4s-1-0.4-1.4,0l-7,7c-0.1,0.1-0.2,0.2-0.2,0.3c-0.1,0.2-0.1,0.5,0,0.8c0.1,0.1,0.1,0.2,0.2,0.3l7,7c0.2,0.2,0.5,0.3,0.7,0.3s0.5-0.1,0.7-0.3c0.4-0.4,0.4-1,0-1.4L7.4,13H19c0.6,0,1-0.4,1-1S19.6,11,19,11z"></path></svg><span class="text" data-v-38ede35f="">Getting Started</span></a></div><div class="next" data-v-38ede35f=""><a class="link" href="javascript:;" data-v-38ede35f=""><span class="text" data-v-38ede35f="">Conditional Rendering</span><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24" class="icon icon-next" data-v-38ede35f=""><path d="M19.9,12.4c0.1-0.2,0.1-0.5,0-0.8c-0.1-0.1-0.1-0.2-0.2-0.3l-7-7c-0.4-0.4-1-0.4-1.4,0s-0.4,1,0,1.4l5.3,5.3H5c-0.6,0-1,0.4-1,1s0.4,1,1,1h11.6l-5.3,5.3c-0.4,0.4-0.4,1,0,1.4c0.2,0.2,0.5,0.3,0.7,0.3s0.5-0.1,0.7-0.3l7-7C19.8,12.6,19.9,12.5,19.9,12.4z"></path></svg></a></div></div></div><!--[--><!--]--></div></main></div><!----><!--]--></div>
    <script>__VP_HASH_MAP__ = JSON.parse("{\"api_index.md\":\"7cb3f7ba\",\"guide_advanced_async-suspense.md\":\"92de39a3\",\"guide_advanced_component-instance.md\":\"2cbac3c7\",\"guide_advanced_http-requests.md\":\"f1cf08b6\",\"guide_advanced_reusability-composition.md\":\"92a6e71f\",\"guide_advanced_slots.md\":\"5fde3872\",\"guide_advanced_stubs-shallow-mount.md\":\"860a1344\",\"guide_advanced_teleport.md\":\"8f99d4c3\",\"guide_advanced_transitions.md\":\"1a2340e7\",\"guide_advanced_vue-router.md\":\"dcf553ad\",\"guide_advanced_vuex.md\":\"e7a8ea91\",\"guide_essentials_a-crash-course.md\":\"2a557e7a\",\"guide_essentials_conditional-rendering.md\":\"ffbbefb8\",\"guide_essentials_easy-to-test.md\":\"4ac41a8f\",\"guide_essentials_event-handling.md\":\"d5aae656\",\"guide_essentials_forms.md\":\"2dd1bff3\",\"guide_essentials_passing-data.md\":\"1d977e0a\",\"guide_extending-vtu_community-learning.md\":\"f15e2ee5\",\"guide_extending-vtu_plugins.md\":\"c9dae1ab\",\"guide_index.md\":\"8d4d1000\",\"index.md\":\"63a4989e\",\"installation_index.md\":\"75fe1f33\",\"migration_index.md\":\"3fe4b12c\"}")</script>
    <script type="module" async="" src="static/js/app.49122d47.js"></script>
    
  </body>
</html>